package mxw.suiye.autopydroid.Server;

import android.accessibilityservice.AccessibilityService;

import android.accessibilityservice.GestureDescription;
import android.content.Intent;
import android.graphics.Path;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;


import androidx.annotation.RequiresApi;


import com.alibaba.fastjson.JSONObject;

import java.util.List;
import java.util.Map;

import mxw.suiye.autopydroid.core.ui.Ui;
import mxw.suiye.autopydroid.util.ThreadUi;
import mxw.suiye.autopydroid.util.MyHandler;
import mxw.suiye.autopydroid.util.ResultData;


/**安卓辅助功能**/
public class AccessibilityServer extends AccessibilityService {

    private AccessibilityNodeInfo rootInfo;
    @Override
    protected void onServiceConnected() {
        keys(GLOBAL_ACTION_HOME);
        try{
            Log.d("辅助服务", "启动服务");
            handleInit();

        } catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public boolean onUnbind(Intent intent) {
        try{
            Log.d("辅助服务", "停止服务");
            MyHandler.nullAccessibility();

        } catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
        rootInfo = getRootInActiveWindow();
    }

    @Override
    public void onInterrupt() {
    }

    private void handleInit(){
        MyHandler.setAccessibilityHandler(msg -> {
            if(msg.what==-1){
                disableSelf();

            } else if(msg.what<10){
                switch (msg.what){
                    case 0:
                        acCheck(msg);
                        break;
                    case 1:
                        keys(GLOBAL_ACTION_BACK);
                        break;
                    case 2:
                        keys(GLOBAL_ACTION_HOME);
                        break;
                    case 3:
                        keys(GLOBAL_ACTION_RECENTS);
                        break;
                    case 4:
                        keys(GLOBAL_ACTION_POWER_DIALOG);
                        break;
                    case 5:
                        keys(GLOBAL_ACTION_NOTIFICATIONS);
                        break;
                    case 6:
                        keys(GLOBAL_ACTION_QUICK_SETTINGS);
                        break;
                    case 7:
                        keys(GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
                        break;
                    case 8:
                        keys(GLOBAL_ACTION_TAKE_SCREENSHOT);
                        break;
                    case 9:
                        keys(GLOBAL_ACTION_LOCK_SCREEN);
                        break;
                    default:break;
                }

            }else if(msg.what<20){
                JSONObject json = (JSONObject)msg.obj;
                int id = json.getIntValue("id");//id == what
                boolean needResult = json.getIntValue("result")==1;
                JSONObject data = json.getJSONObject("data");
                switch (msg.what){
                    case 10:
                        returnNode();
                        break;
                    case 11:
                        gesture(msg);
                        break;
                    case 12:
                        click(msg);
                        break;
                    case 13:
                        input(msg);
                        break;
                    case 14:
                        getNodeInfo(msg);
                        break;
                    default:break;
                }
            }
            return true;
        });
    }

    void acCheck(Message msg){
        ResultData.reply("无障碍启动");
        Ui.toast("无障碍启动");
    }

    void returnNode(){
        ResultData.reply(rootInfo.toString());
    }

    void keys(int action){
        performGlobalAction(action);
    }

    void gesture(Message msg){
        JSONObject data = ((JSONObject) msg.obj).getJSONObject("data");

        int x1 = data.getIntValue("x1");
        int y1 = data.getIntValue("y1");
        int x2 = data.getIntValue("x2");
        int y2 = data.getIntValue("y2");
        int duration = data.getIntValue("duration");

        Path path= new Path();
        path.moveTo(x1, y1);
        if (x2 != 0 || y2 != 0) {
            path.lineTo(x2, y2);
        }
        GestureDescription.Builder builder = new GestureDescription.Builder();
        builder.addStroke(new GestureDescription.StrokeDescription(path, 0, duration));
        GestureDescription gesture = builder.build();

        dispatchGesture(gesture, null, null);
        ResultData.reply("无效请求");
    }

    //TODO 优化
    void click(Message msg){
        JSONObject data = ((JSONObject) msg.obj).getJSONObject("data");
        String text = data.getString("text");
        int order = data.getIntValue("order");

        List<AccessibilityNodeInfo> results = rootInfo.findAccessibilityNodeInfosByText(text);
        if(results.size()>0&&order<results.size()){
            AccessibilityNodeInfo node = results.get(order);
            while (node!=null){
                if(node.isClickable()){
                    node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    ResultData.reply("0");
                    return;
                }
                node = node.getParent();
            }
            ResultData.reply("找到："+text+" 但不可点击");
        } else {
            ResultData.reply("未找到："+text+" 或order超出");
        }
    }

    //TODO 优化
    void input(Message msg){
        JSONObject data = ((JSONObject) msg.obj).getJSONObject("data");

        input_s(rootInfo, data.getString("text"), data.getIntValue("order"));
        ResultData.reply("0");
    }

    void input_s(AccessibilityNodeInfo node, String text, int order){
        for(int i=0;i<node.getChildCount();i++){
            AccessibilityNodeInfo node_c = node.getChild(i);
            try{
                if(node_c.isEditable()){
                    Bundle data = new Bundle();
                    data.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
                    node_c.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, data);
                    return;
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            input_s(node_c, text, order);
        }
    }

    AccessibilityNodeInfo findNodeByText(String text){
        List<AccessibilityNodeInfo> results = rootInfo.findAccessibilityNodeInfosByText(text);
        if(results.size()>0){
            return results.get(0);
        }
        return null;
    }

    //TODO 实现
    void getNodeInfo(Message msg){

        JSONObject json = (JSONObject) msg.obj;
        boolean needResult = json.getIntValue("result")==1;
        if(!needResult){
            return;
        }
        int target = msg.arg1;
        JSONObject data = json.getJSONObject("data");

        AccessibilityNodeInfo rootNode = findNodeByText(data.getString("text"));
        if(rootNode==null){
            ResultData.reply("-1");
            return;
        }

        String fullId = "";
        if(rootNode.getViewIdResourceName()!=null){
            fullId = rootNode.getViewIdResourceName();
        }
        String className = "";
        if(rootNode.getClassName()!=null){
            className = rootNode.getClassName().toString();
        }
        String packageName = "";
        if(rootNode.getPackageName()!=null){
            packageName = rootNode.getPackageName().toString();
        }
        String desc = "";
        if(rootNode.getContentDescription()!=null){
            desc = rootNode.getContentDescription().toString();
        }
        String text = "";
        if(rootNode.getText()!=null){
            text = rootNode.getText().toString();
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("fullId", fullId);
        jsonObject.put("className", className);
        jsonObject.put("packageName", packageName);
        jsonObject.put("text", text);
        jsonObject.put("desc", desc);

        ResultData.reply(jsonObject.toJSONString());
    }


}


